package org.ch02.test00.demo08.teacherWork;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自动生成SQl语句
 * @author CSY
 * @date 2025 - 03 - 20
 */
public class SqlGenerate {
    /**
     * 基于 Bean（实体） 对象，生成查询所有字段的语句
     * @param beanClazz 实体对象的Class对象
     * @return 查询所有字段的SqL语句
     */
    public static String generateSelect(Class<?> beanClazz){
        StringBuilder sql = new StringBuilder("select ");

        //获取实体对象的所有字段
        Field[] declaredFields = beanClazz.getDeclaredFields();

        //循环拼接字段
        for (Field field : declaredFields) {
            field.setAccessible(true);
            sql.append(convertToSnake(field.getName())).append(",");
        }
        //删除某个下标的字符 - 删除最后的,
        sql.deleteCharAt(sql.length() - 1);
        sql.append(" from ").append(convertToSnake(beanClazz.getSimpleName()));

        return sql.toString();
    }

    /**
     * 重载 - 基于Bean对象生成查询所有字段的语句，并且根据Map集合指定的参数拼接查询条件
     * @param beanClazz 实体对象的Class对象
     * @param cond 查询条件
     * @return 带条件且查询所有字段的SQL语句
     */
    public static String generateSelect(Class<?> beanClazz, Map<String,Object> cond){//健壮性
        //调用重载方法，获取查询所有字段的SQL语句
        StringBuilder sql = new StringBuilder(generateSelect(beanClazz));

        if (cond == null && cond.size() == 0){
            return sql.toString();
        }
        sql.append(" where ");
        for (Map.Entry<String, Object> entry : cond.entrySet()) {
            sql.append(entry.getKey()).append("= ?").append(" and ");
        }

        return sql.substring(0, sql.length() - 5).toString();
    }

    /**
     * 根据bean对象，生成对应的添加数据的SQL语句
     * @param beanClass Bean对象 - 与数据表对应
     * @return insert SQL
     */
    public static String generateInsert(Class<?> beanClass){
        StringBuilder sql = new StringBuilder("insert into ");

        //将表名获取到并转换为数据库命名规范
        String tableName = convertToSnake(beanClass.getSimpleName());
        sql.append(tableName).append("(");

        //玄幻遍历Bean对象中的所有字段 - 注意：Bean对象 的字段与数据表的字段一一对应
        Field[] fields = beanClass.getDeclaredFields();
        for (Field f : fields) {
            sql.append(convertToSnake(f.getName())).append(",");
        }
        sql.deleteCharAt(sql.length() - 1);
        sql.append(") values(");

        for (int i = 0; i < fields.length; i++) {
            sql.append("?").append(",");
        }
        sql.deleteCharAt(sql.length() - 1);
        sql.append(")");

        return sql.toString();
    }

    /**
     * 实现把驼峰命名的字符串转换为数据库的命名规范
     * xxxXxxXxx - xxx_xxx_xxx
     * XxxXxx - xxx_xxx
     *
     * @param input 要转换的字符
     * @return 转换后的字符
     */
    public static String convertToSnake(String input){
        return input.replaceAll("(?<!^)([A-Z])","_$1").toLowerCase();
    }

    /**
     *
     * 实现把数据库的命名规范转换为驼峰命名的字符串
     * @param input 蛇形命名的字符串
     * @return 驼峰命名的字符串
     */
    public static String convertToCamel(String input) {
        // 使用正则表达式匹配下划线及其后的字母
        Pattern pattern = Pattern.compile("_([a-z])");
        Matcher matcher = pattern.matcher(input);
        StringBuffer sb = new StringBuffer();

        while (matcher.find()) {
            // 将下划线后的字母转换为大写
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);

        return sb.toString();
    }
}
